from google.appengine.ext import db
from gaeo.controller import BaseController

from gae import AppEngineOAuthClient
from provider import ProviderRepository
import oauthlib.oauth as oauth

import logging
import urllib
import urlparse
import random
import string

class OauthController(BaseController):
  def bind(self):
    site_url = self.params.get('site_url')
    token = ''.join([ random.choice(string.digits + string.letters) for i in range(64) ])
    self.session['site_url_' + token] = site_url
    self.session.put()
    self.render(json=self.to_json({ "token" : token }))

  def proxy(self):
    request_url = self.params.get('url')
    logging.info("request_url : %s" % request_url)
    provider = ProviderRepository.find_provider(request_url)
    if provider:
      token_key, token_secret = self._get_access_token_key_and_secret(provider)
      site_url = self.session.get('site_url_' + self.params.get('token'))
      logging.info("site_url : %s" % site_url)
      xd_authorized = self._is_xd_authorized(provider, site_url)
      if token_key and token_secret and xd_authorized:
        client = AppEngineOAuthClient(provider)
        access_token = oauth.OAuthToken(token_key, token_secret)
        content = client.access_resource(access_token, request_url)
        self.render(text=content)
      else:
        self.response.set_status(401)
        self.render(html='<h1>Authorization Required</h1>')
    else:
      self.response.set_status(404)
      self.render(html='<h1>OAuth Provider not found.</h1>')

  def _get_access_token_key_and_secret(self, provider):
    token_search_key = 'access_token_' + str(provider.id)
    secret_search_key = 'access_token_secret_' + str(provider.id)
    token_key = self.session.get(token_search_key)
    token_secret = self.session.get(secret_search_key)
    return token_key, token_secret

  def _is_xd_authorized(self, provider, site_url):
    if provider and site_url: 
      domain = urlparse.urlparse(site_url)[1]
      xd_authorize_search_key = 'xd_authorized_' + str(provider.id) + '_' + domain
      return self.session.get(xd_authorize_search_key)
    else:
      return False

  def authorize(self):
    request_url = self.params.get('request_url')
    provider = ProviderRepository.find_provider(request_url)
    if provider:
      token_key, token_secret = self._get_access_token_key_and_secret(provider)
      if token_key and token_secret:
        self.redirect('/oauth/xd_authorize?' + self.request.query_string)
      else:
        client = AppEngineOAuthClient(provider)
        request_token = client.fetch_request_token()
        secret_search_key = 'request_token_secret_' + request_token.key
        provider_search_key = 'request_token_provider_' + request_token.key
        params_search_key = 'request_token_params_' + request_token.key
        self.session[secret_search_key] = request_token.secret
        self.session[provider_search_key] = provider.id
        self.session[params_search_key] = self.request.query_string
        self.session.put()
        callback_url = "/".join(self.request.url.split("/")[0:3]) + '/oauth/callback'
        redirect_url= client.create_authorization_redirect_url(request_token, callback_url)
        self.redirect(redirect_url)
    else:
      self.response.set_status(404)
      self.render(html='<h1>OAuth Provider not found.</h1>')

  def callback(self):
    token_key = self.params['oauth_token']
    secret_search_key = 'request_token_secret_' + token_key
    provider_search_key = 'request_token_provider_' + token_key
    params_search_key = 'request_token_params_' + token_key
    token_secret = self.session.get(secret_search_key)
    provider = ProviderRepository.find(self.session.get(provider_search_key))
    saved_params = self.session.get(params_search_key)

    if token_key and token_secret and provider:
      authorized_token = oauth.OAuthToken(token_key, token_secret)
      client = AppEngineOAuthClient(provider)
      access_token = client.fetch_access_token(authorized_token)
      token_search_key = 'access_token_' + str(provider.id)
      secret_search_key = 'access_token_secret_' + str(provider.id)
      self.session[token_search_key] = access_token.key
      self.session[secret_search_key] = access_token.secret
      self.session.put()

      self.redirect('/oauth/xd_authorize?' + saved_params)
    else:
      self.response.set_status(500)
      self.render(html='<h1>Server Error</h1>')

  def xd_authorize(self):
    request_url = self.params.get('request_url')
    provider = ProviderRepository.find_provider(request_url)
    if provider:
      site_url = self.session.get('site_url_' + self.params.get('site_token'))
      if site_url and self.params.get('ok') == 'ok' and self.params.get('csrf_token') == self.session._id:
        domain = urlparse.urlparse(site_url)[1]
        xd_authorize_search_key = 'xd_authorized_' + str(provider.id) + '_' + domain
        self.session[xd_authorize_search_key] = True
        self.session.put()
        self.render(html='<html><head><script type="text/javascript">window.close()</script></head></html>')
      else:
        xd_authorized = self._is_xd_authorized(provider, site_url)
        if xd_authorized:
          self.render(html='<html><head><script type="text/javascript">window.close()</script></head></html>')
        else:
          self.request_url = request_url
          self.site_token = self.params.get('site_token')
          self.session_id = self.session._id
          self.provider = provider
          self.domain = urlparse.urlparse(site_url)[1]
    else:
      self.response.set_status(404)
      self.render(html='<h1>OAuth Provider not found.</h1>')






